package com.dounion.sample.service.impl;

import com.dounion.framework.entity.Model;
import com.dounion.framework.entity.PageVo;
import com.dounion.framework.helper.AssertHelper;
import com.dounion.framework.helper.DataHelper;
import com.dounion.framework.helper.DateHelper;
import com.dounion.framework.helper.ValidHelper;
import com.dounion.sample.entity.Stock;
import com.dounion.sample.entity.StockHistory;
import com.dounion.sample.entity.TsDetails;
import com.dounion.sample.mapper.StockHistoryMapper;
import com.dounion.sample.mapper.StockMapper;
import com.dounion.sample.mapper.TsDetailsMapper;
import com.dounion.sample.service.StockService;
import com.dounion.sample.utils.StockUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.statement.select.ValuesList;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

import static com.dounion.sample.common.Constant.CURRENT_KEY;

@Service
@Slf4j
public class StockServiceImpl implements StockService {

    @Resource
    StockMapper stockMapper;

    @Resource
    StockHistoryMapper stockHistoryMapper;

    @Resource
    TsDetailsMapper tsDetailsMapper;


    /**
     * 分页查询
     *
     * @param query
     * @param pageVo
     * @return
     */
    @Override
    public PageInfo findByPage(StockHistory query, PageVo pageVo) {
        PageHelper.startPage(pageVo.getPageNo(), pageVo.getPageSize());
        log.info("orderby=" + query.getOrderBy());
        return new PageInfo(stockHistoryMapper.selectListBySelective(query));
    }

    /**
     * 通过code获取详情
     *
     * @param code
     * @return
     */
    public Stock findByCode(String code) {
        Stock query = new Stock();
        query.setCode(code);
        List<Stock> stocks = stockMapper.selectListBySelective(query);
        if (ValidHelper.isEmpty(stocks)) {
            return null;
        }
        return stocks.get(0);
    }


    /**
     * 更新指数
     *
     * @param query
     * @return
     */
    @Override
    public Object save(Model query) {
        AssertHelper.EX_VALIDATION.isNotEmpty(query, "symbol", "common.parameter_required.symbol");
        Model input = Model.builder();
        input.set("symbol", query.getString("symbol"));
        input.set("begin", DataHelper.getString(System.currentTimeMillis()));
        input.set("period", query.getString("period", "day"));
        input.set("type", query.getString("type", "before"));
        input.set("count", query.getString("count", "-1"));
        input.set("indicator", query.getString("indicator", "kline,pe,pb,ps,pcf,market_capital,agt,ggt,balance"));

        List<ArrayList> list = StockUtils.loadStockDaily(input);
        if (ValidHelper.isEmpty(list)) {
            return null;
        }
        StockHistory querySh = new StockHistory();
        querySh.setCode(query.getString("symbol"));
        List<StockHistory> stockHistories = stockHistoryMapper.selectListBySelective(querySh);

        //d本身就是一个arrayList
        list.forEach(d -> {
            StockHistory sh = new StockHistory();
            sh.setCode(query.getString("symbol"));
            sh.setHiTimestamp(DataHelper.getString(d.get(0)));
            Timestamp ts = new Timestamp(DataHelper.getLong(sh.getHiTimestamp()));
            sh.setHiDate(DateHelper.format(ts.toLocalDateTime()));
            sh.setOpen(DataHelper.getString(d.get(2)));
            sh.setHigh(DataHelper.getString(d.get(3)));
            sh.setLow(DataHelper.getString(d.get(4)));
            sh.setClose(DataHelper.getString(d.get(5)));
            sh.setChg(DataHelper.getString(d.get(6)));
            sh.setPercent(DataHelper.getString(d.get(7)));
            //更新
            if (stockHistories.stream()
                    .filter(x -> ValidHelper.isEquals(sh.getHiTimestamp(), x.getHiTimestamp()))
                    .count() > 0) {
                sh.setUpdateDate(DateHelper.formatNow());
                stockHistoryMapper.updateBySelective(sh);
            } else {
                sh.setCreateDate(DateHelper.formatNow());
                stockHistoryMapper.insertSelective(sh);
            }
        });
        return list.size();
    }

    @Override
    public Object updateAll(Model query) {
        Stock queryStock = new Stock();
        List<Stock> stocks = stockMapper.selectListBySelective(queryStock);
        stocks.forEach(d -> {
            this.save(Model.builder().set("symbol", d.getCode()).set("count", query.getString("count", "-1")));
        });
        return stocks.size();
    }

    @Override
    public List list(Model input) {
        PageVo pageVo = new PageVo();
        pageVo.setPageNo(1);
        pageVo.setPageSize(input.getInt("day", 1));

        Stock queryStock = new Stock();
        List<Stock> stocks = stockMapper.selectListBySelective(queryStock);
        return stocks.stream().map(d -> {
            //1.先更新今天的涨幅
            Model querySt = Model.builder();
            querySt.set("symbol", d.getCode());
            this.save(querySt);

            //2.查询并计算
            StockHistory querySh = new StockHistory();
            querySh.setCode(d.getCode());
            querySh.setOrderBy("T.HI_DATE desc");
            PageInfo<StockHistory> byPage = this.findByPage(querySh, pageVo);
            List<StockHistory> list = byPage.getList();

            Model builder = Model.builder();
            builder.set("代码", d.getCode());
            builder.set("名称", d.getName());
            builder.set("涨幅", calculateDun(list));
            return builder;
        }).sorted((x, y) -> {
            return new BigDecimal(y.getString("涨幅")).compareTo(new BigDecimal(x.getString("涨幅")));
        }).collect(Collectors.toList());

    }


    /**
     * 添加交易记录
     *
     * @param tsDetails
     * @return
     */
    @Override
    public Object addTs(TsDetails tsDetails) {
        AssertHelper.EX_VALIDATION.isNotBlank(tsDetails.getCode(), "common.parameter_required.code");
        AssertHelper.EX_VALIDATION.isNotEmpty(tsDetails.getTsCount(), "common.parameter_required.tsCount");
        //填充冗余
        Stock stock = this.findByCode(tsDetails.getCode());
        if (ValidHelper.isNotEmpty(stock)) {
            tsDetails.setName(stock.getName());
        }
        //如果没有传买入价格就获取当前价格
        if (ValidHelper.isEmpty(tsDetails.getTsUnitprice())) {
            Model pankou = StockUtils.pankou(tsDetails.getCode());
            tsDetails.setTsUnitprice(pankou.getBigDecimal(CURRENT_KEY));
        }
        //默认是买入
        if (ValidHelper.isNull(tsDetails.getTsType())){
            tsDetails.setTsType(0);
        }
        tsDetails.setTsPrice(tsDetails.getTsUnitprice().multiply(DataHelper.getBigDecimal(tsDetails.getTsCount())));
        tsDetails.setTsDate(DateHelper.formatNow());
        tsDetails.setCrateDate(DateHelper.formatNow());
        tsDetailsMapper.insertSelective(tsDetails);
        return tsDetails.getId();
    }

    /**
     *
     * @param input
     * @return
     */
    @Override
    public Object calculate(Model input) {
        TsDetails tsQuery=new TsDetails();
        // TODO: 2021/8/3 后期改进为组合
        tsQuery.setCodeQueryIn("SH510300,SH510500,SZ159915,SH513100,SH513050");
        tsQuery.setOrderBy("T.TS_DATE DESC");
        List<TsDetails> tsDetails = tsDetailsMapper.selectListBySelective(tsQuery);

        TsDetails details=null;
        //获取最新的交易 （临时这样处理，最后一次为卖出 即考虑为当前是空仓）
        if (ValidHelper.isNotEmpty(tsDetails)){
            details=tsDetails.get(0);
            if (ValidHelper.isEquals(details.getTsType(), 1)){
                details=null;
            }
        }

        //计算最近的 最近20的涨幅情况

        //用于存储涨幅大于2的
        List<Model> listZf=Lists.newArrayList();
        Model query = Model.builder();
        query.set("day","20");
        List list = this.list(query);
        list.stream().forEach(d->{
            Model model = Model.parseObject(d);
            //如果涨幅大于2
            if (new BigDecimal(model.getString("涨幅")).compareTo(new BigDecimal(2))>0){
                listZf.add(model);
            }
        });





        //如果当前是空仓
        if (ValidHelper.isEmpty(details)){
            if (ValidHelper.isEmpty(listZf)){
                return "当前需要保持清仓";
            }
            Model modelZf = listZf.get(0);
            return "当前需要买入 代码【"+modelZf.getString("代码")+"】,名称【"+modelZf.getString("名称")+"】,最近20天涨幅【"+modelZf.getString("涨幅")+ "】";
        }


        //如果当前正持有仓位
        if (ValidHelper.isNotEmpty(details)){
            TsDetails finalDetails = details;
            Optional<Model> modelOptional = listZf.stream().filter(d -> d.equals("代码", finalDetails.getCode())).findFirst();
            //如果找到了
            if (modelOptional.isPresent()){
                Model model = modelOptional.get();
                return "当前需要保持持仓不变 代码【"+model.getString("代码")+"】,名称【"+model.getString("名称")+"】,最近20天涨幅【"+model.getString("涨幅")+ "】";
            }
            else {
                Model modelZf = listZf.get(0);
                return "当前需要卖出代码【"+finalDetails.getCode()+"】,名称【"+finalDetails.getName()+"】 /n/t 买入代码【"+modelZf.getString("代码")+"】,名称【"+modelZf.getString("名称")+"】,最近20天涨幅【"+modelZf.getString("涨幅")+ "】";
            }
        }
        return "";
    }

    /**
     * 统计重量
     *
     * @param list
     * @return
     */
    private BigDecimal calculateDun(List<StockHistory> list) {
        Optional<BigDecimal> reduce =
                list.stream().map(d -> new BigDecimal(d.getPercent())).reduce((x, y) -> x.add(y));
        if (reduce.isPresent()) {
            //return DataHelper.divide(DataHelper.getBigDecimal(reduce.get()),new BigDecimal(1000),3);
            return reduce.get();
        }
        return new BigDecimal(0);
    }
}
